package com.datareport.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.datareport.common.exception.BusinessException;
import com.datareport.domain.entity.StatRule;
import com.datareport.repository.StatRuleRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * 规则配置服务
 */
@Service
@Slf4j
public class RuleService {
    @Autowired
    private StatRuleRepository ruleRepository;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    /**
     * 创建统计规则
     * @param rule 规则配置
     * @return 规则ID
     */
    @Transactional
    public String createRule(StatRule rule) {
        // 1. 验证规则配置
        validateRule(rule);
        
        // 2. 保存规则
        rule.setStatus(1);
        rule.setCreateTime(LocalDateTime.now());
        rule.setUpdateTime(LocalDateTime.now());
        rule.setEffectTime(LocalDateTime.now().plusSeconds(3)); // 3秒后生效
        ruleRepository.insert(rule);
        
        // 3. 异步触发规则生效
        asyncTriggerRule(rule);
        
        return rule.getRuleId();
    }
    
    /**
     * 更新统计规则
     * @param rule 规则配置
     */
    @Transactional
    public void updateRule(StatRule rule) {
        // 1. 检查规则是否存在
        StatRule existingRule = ruleRepository.selectById(rule.getRuleId());
        if (existingRule == null) {
            throw new BusinessException("规则不存在");
        }
        
        // 2. 验证规则配置
        validateRule(rule);
        
        // 3. 更新规则
        rule.setUpdateTime(LocalDateTime.now());
        rule.setEffectTime(LocalDateTime.now().plusSeconds(3)); // 3秒后生效
        ruleRepository.updateById(rule);
        
        // 4. 清除缓存
        redisTemplate.delete("rule:" + rule.getRuleId());
        
        // 5. 异步触发规则生效
        asyncTriggerRule(rule);
    }
    
    /**
     * 更新规则状态
     * @param ruleId 规则ID
     * @param status 状态
     */
    @Transactional
    public void updateRuleStatus(String ruleId, Integer status) {
        StatRule rule = ruleRepository.selectById(ruleId);
        if (rule == null) {
            throw new BusinessException("规则不存在");
        }
        
        // 更新状态
        rule.setStatus(status);
        rule.setUpdateTime(LocalDateTime.now());
        ruleRepository.updateById(rule);
        
        // 清除缓存
        redisTemplate.delete("rule:" + ruleId);
    }
    
    /**
     * 删除规则
     * @param ruleId 规则ID
     */
    @Transactional
    public void deleteRule(String ruleId) {
        StatRule rule = ruleRepository.selectById(ruleId);
        if (rule == null) {
            throw new BusinessException("规则不存在");
        }
        
        // 删除规则
        ruleRepository.deleteById(ruleId);
        
        // 清除缓存
        redisTemplate.delete("rule:" + ruleId);
    }
    
    /**
     * 获取规则详情
     * @param ruleId 规则ID
     * @return 规则详情
     */
    public StatRule getRule(String ruleId) {
        StatRule rule = ruleRepository.selectById(ruleId);
        if (rule == null) {
            throw new BusinessException("规则不存在");
        }
        return rule;
    }
    
    /**
     * 分页查询规则列表
     * @param page 页码
     * @param size 每页大小
     * @param name 规则名称（可选）
     * @param status 状态（可选）
     * @return 规则列表
     */
    public Page<StatRule> listRules(int page, int size, String name, Integer status) {
        Page<StatRule> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<StatRule> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (name != null && !name.isEmpty()) {
            queryWrapper.like(StatRule::getName, name);
        }
        
        if (status != null) {
            queryWrapper.eq(StatRule::getStatus, status);
        }
        
        // 按创建时间降序排序
        queryWrapper.orderByDesc(StatRule::getCreateTime);
        
        return ruleRepository.selectPage(pageParam, queryWrapper);
    }
    
    /**
     * 验证规则配置
     * @param rule 规则配置
     */
    private void validateRule(StatRule rule) {
        if (rule.getName() == null || rule.getName().isEmpty()) {
            throw new BusinessException("规则名称不能为空");
        }
        
        if (rule.getTables() == null || rule.getTables().isEmpty()) {
            throw new BusinessException("关联表不能为空");
        }
        
        if (rule.getGroupFields() == null || rule.getGroupFields().isEmpty()) {
            throw new BusinessException("分组字段不能为空");
        }
        
        if (rule.getAggFields() == null || rule.getAggFields().isEmpty()) {
            throw new BusinessException("聚合字段不能为空");
        }
        
        // 验证JSON格式
        try {
            // 这里可以添加JSON格式验证逻辑
        } catch (Exception e) {
            throw new BusinessException("配置格式不正确: " + e.getMessage());
        }
    }
    
    /**
     * 异步触发规则生效
     * @param rule 规则配置
     */
    private void asyncTriggerRule(StatRule rule) {
        CompletableFuture.runAsync(() -> {
            try {
                // 等待规则生效时间
                long delaySeconds = 3;
                if (rule.getEffectTime() != null) {
                    delaySeconds = Math.max(1, java.time.Duration.between(LocalDateTime.now(), rule.getEffectTime()).getSeconds());
                }
                
                TimeUnit.SECONDS.sleep(delaySeconds);
                
                // 将规则配置保存到Redis，供Flink任务使用
                String ruleKey = "rule:" + rule.getRuleId();
                redisTemplate.opsForValue().set(ruleKey, com.alibaba.fastjson2.JSON.toJSONString(rule));
                
                log.info("规则 {} 已生效", rule.getRuleId());
            } catch (Exception e) {
                log.error("触发规则生效失败: {}", e.getMessage(), e);
            }
        });
    }
}